home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Blender 2.49b / blender-2.49b-windows.exe / $_4_ / .blender / scripts / image_billboard.py < prev    next >
Text File  |  2009-08-31  |  8KB  |  270 lines

  1. #!BPY
  2. """
  3. Name: 'Billboard Render on Active'
  4. Blender: 242
  5. Group: 'Image'
  6. Tooltip: 'Selected objects and lamps to rendered faces on the act mesh'
  7. """ 
  8. __author__= "Campbell Barton"
  9. __url__= ["blender", "blenderartist"]
  10. __version__= "1.0"
  11.  
  12. __bpydoc__= """\
  13. Render Billboard Script
  14. This can texture a simple billboard mesh from any number of selected objects.
  15.  
  16. Renders objects in the selection to quad faces on the active mesh.
  17.  
  18. Usage
  19. * Light your model or enable the shadless flag so it is visible
  20. * Make a low poly mesh out of quads with 90d corners. (this will be you billboard mesh)
  21. * Select the model and any lamps that light it
  22. * Select the billboard mesh so that it is active
  23. * Run this script, Adjust settings such as image size or oversampling.
  24. * Select a place to save the PNG image.
  25. * Once the script has finished running return to the 3d view by pressing Shift+F5
  26. * To see the newly applied textures change the drawtype to 'Textured Solid'
  27. """
  28. # ***** BEGIN GPL LICENSE BLOCK *****
  29. #
  30. # Script copyright (C) Campbell J Barton 2006
  31. #
  32. # This program is free software; you can redistribute it and/or
  33. # modify it under the terms of the GNU General Public License
  34. # as published by the Free Software Foundation; either version 2
  35. # of the License, or (at your option) any later version.
  36. #
  37. # This program is distributed in the hope that it will be useful,
  38. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  39. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  40. # GNU General Public License for more details.
  41. #
  42. # You should have received a copy of the GNU General Public License
  43. # along with this program; if not, write to the Free Software Foundation,
  44. # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  45. #
  46. # ***** END GPL LICENCE BLOCK *****
  47. # --------------------------------------------------------------------------
  48.  
  49. import Blender
  50. from Blender import Mesh, Material, Draw
  51. import BPyMathutils
  52. import bpy
  53. import BPyRender
  54. from Blender.Scene import Render
  55.  
  56. # reload(BPyRender)
  57. # reload(BPyMathutils)
  58.  
  59. import os
  60. Vector= Blender.Mathutils.Vector
  61.  
  62. def alpha_mat(image):
  63.     # returns a material useable for 
  64.     mtl= bpy.data.materials.new()
  65.     mtl.mode |= (Material.Modes.SHADELESS | Material.Modes.ZTRANSP | Material.Modes.FULLOSA | Material.Modes.TEXFACE | Material.Modes.TEXFACE_ALPHA )
  66.     return mtl
  67.  
  68. # PupBlock Settings
  69. GLOBALS= {}
  70. PREF_RES= Draw.Create(512)
  71. PREF_TILE_RES= Draw.Create(256)
  72. PREF_AA = Draw.Create(1)
  73. PREF_ALPHA= Draw.Create(1)
  74. PREF_Z_OFFSET = Draw.Create(10.0)
  75. PREF_IMG_PACK= Draw.Create(1)
  76.  
  77.  
  78. def save_billboard(PREF_IMAGE_PATH):
  79.     Blender.Window.WaitCursor(1)
  80.     # remove png, add it later
  81.     PREF_IMAGE_PATH= PREF_IMAGE_PATH.replace('.png', '')
  82.     
  83.     ob_sel= GLOBALS['ob_sel']
  84.     me_ob = GLOBALS['me_ob']
  85.     me_data = GLOBALS['me_data']
  86.     
  87.     time= Blender.sys.time()
  88.     
  89.     me_mat= me_ob.matrixWorld
  90.     
  91.     # Render images for all faces
  92.     face_data= [] # Store faces, images etc
  93.     boxes2Pack= []
  94.     me_data.faceUV= True
  95.     
  96.     for i, f in enumerate(me_data.faces):
  97.         no= f.no
  98.         
  99.         # Offset the plane by the zoffset on the faces normal
  100.         plane= [v.co * me_mat for v in f]
  101.         
  102.         # Horizontal stacking, make sure 0,1 and 2,3 are the longest
  103.         if\
  104.         (plane[0]-plane[1]).length + (plane[2]-plane[3]).length < \
  105.         (plane[1]-plane[2]).length + (plane[3]-plane[0]).length:
  106.             plane.append(plane.pop(0))
  107.             rot90= True
  108.         else:
  109.             rot90= False
  110.         
  111.         no= Blender.Mathutils.QuadNormal(*plane)
  112.         plane= [v + no*PREF_Z_OFFSET.val for v in plane]
  113.         
  114.         cent= (plane[0]+plane[1]+plane[2]+plane[3] ) /4.0
  115.         camera_matrix= BPyMathutils.plane2mat(plane)
  116.         tmp_path= '%s_%d' % (PREF_IMAGE_PATH, i)
  117.         img= BPyRender.imageFromObjectsOrtho(ob_sel, tmp_path, PREF_TILE_RES.val, PREF_TILE_RES.val, PREF_AA.val, PREF_ALPHA.val, camera_matrix)
  118.         img.reload()
  119.         #img.pack() # se we can keep overwriting the path
  120.         #img.filename= ""
  121.         
  122.         if rot90:
  123.             f.uv=Vector(1,1), Vector(0,1), Vector(0,0), Vector(1,0)
  124.         else:    
  125.             f.uv= Vector(0,1), Vector(0,0), Vector(1,0), Vector(1,1)
  126.         
  127.         if not PREF_IMG_PACK.val:
  128.             f.mode |= Mesh.FaceModes.TEX
  129.             f.image = img
  130.             
  131.             if PREF_ALPHA.val:
  132.                 f.transp |= Mesh.FaceTranspModes.ALPHA
  133.         else:
  134.             w= ((plane[0]-plane[1]).length + (plane[2]-plane[3]).length)/2
  135.             h= ((plane[1]-plane[2]).length + (plane[3]-plane[0]).length)/2
  136.             
  137.             face_data.append( (f, img) )
  138.             boxes2Pack.append( [0.0,0.0,h, w, i] )
  139.     
  140.     if PREF_IMG_PACK.val:
  141.         # pack the quads into a square
  142.         packWidth, packHeight = Blender.Geometry.BoxPack2D(boxes2Pack)
  143.         
  144.         render_obs= []
  145.         
  146.         render_mat= alpha_mat(img)
  147.         
  148.         # Add geometry to the mesh
  149.         for box in boxes2Pack:
  150.             i= box[4]
  151.             
  152.             orig_f, img= face_data[i]
  153.             
  154.             # New Mesh and Object
  155.             
  156.             render_me= bpy.data.meshes.new()
  157.             
  158.             render_ob= Blender.Object.New('Mesh')
  159.             render_me.materials= [render_mat]
  160.             render_ob.link(render_me)
  161.             
  162.             render_obs.append(render_ob)
  163.             
  164.             # Add verts clockwise from the bottom left.
  165.             _x= box[0] / packWidth
  166.             _y= box[1] / packHeight
  167.             _w= box[2] / packWidth
  168.             _h= box[3] / packHeight
  169.             
  170.             
  171.             render_me.verts.extend([\
  172.             Vector(_x, _y, 0),\
  173.             Vector(_x, _y +_h, 0),\
  174.             Vector(_x + _w, _y +_h, 0),\
  175.             Vector(_x + _w, _y, 0),\
  176.             ])
  177.                 
  178.             render_me.faces.extend(list(render_me.verts))
  179.             render_me.faceUV= True
  180.             
  181.             render_me.faces[0].uv = [Vector(0,0), Vector(0,1), Vector(1,1), Vector(1,0)]
  182.             render_me.faces[0].image = img
  183.             
  184.             # Set the UV's, we need to flip them HOZ?
  185.             for uv in orig_f.uv:
  186.                 uv.x = _x + (uv.x * _w)
  187.                 uv.y = _y + (uv.y * _h)
  188.         
  189.         target_image= BPyRender.imageFromObjectsOrtho(render_obs, PREF_IMAGE_PATH, PREF_RES.val, PREF_RES.val, PREF_AA.val, PREF_ALPHA.val, None)
  190.         target_image.reload() # incase your overwriting an existing image.
  191.         
  192.         # Set to the 1 image.
  193.         for f in me_data.faces:
  194.             f.image= target_image
  195.             if PREF_ALPHA.val:
  196.                 f.transp |= Mesh.FaceTranspModes.ALPHA
  197.         
  198.         # Free the images data and remove
  199.         for data in face_data:
  200.             img= data[1]
  201.             os.remove(img.filename)
  202.             img.reload()
  203.             
  204.     # Finish pack
  205.     
  206.     me_data.update()
  207.     me_ob.makeDisplayList()
  208.     Blender.Window.WaitCursor(0)
  209.     print '%.2f secs taken' % (Blender.sys.time()-time)
  210.  
  211.  
  212. def main():
  213.     scn= bpy.data.scenes.active
  214.     ob_sel= list(scn.objects.context)
  215.     
  216.     PREF_KEEP_ASPECT= False
  217.     
  218.     # Error Checking
  219.     if len(ob_sel) < 2:
  220.         Draw.PupMenu("Error%t|Select 2 mesh objects")
  221.         return
  222.         
  223.     me_ob= scn.objects.active
  224.     
  225.     if not me_ob:
  226.         Draw.PupMenu("Error%t|No active mesh selected.")
  227.     
  228.     try:
  229.         ob_sel.remove(me_ob)
  230.     except:
  231.         pass
  232.     
  233.     if me_ob.type != 'Mesh':
  234.         Draw.PupMenu("Error%t|Active Object must be a mesh to write billboard images too")
  235.         return
  236.     
  237.     me_data= me_ob.getData(mesh=1)
  238.     
  239.     for f in me_data.faces:
  240.         if len(f) != 4:
  241.             Draw.PupMenu("Error%t|Active mesh must have only quads")
  242.             return
  243.     
  244.     
  245.     # Get user input
  246.     block = [\
  247.     'Image Pixel Size',\
  248.     ("Packed Size: ", PREF_RES, 128, 2048, "Pixel width and height to render the billboard to"),\
  249.     ("Tile Size: ", PREF_TILE_RES, 64, 1024, "Pixel  width and height for each tile to render to"),\
  250.     'Render Settings',\
  251.     ("Pack Final", PREF_IMG_PACK , "Pack the image for each face into images into a single image"),\
  252.     ("Oversampling", PREF_AA , "Higher quality woth extra sampling"),\
  253.     ("Alpha Clipping", PREF_ALPHA , "Render empty areas as transparent"),\
  254.     ("Cam ZOffset: ", PREF_Z_OFFSET, 0.1, 100, "Distance to place the camera away from the quad when rendering")\
  255.     ]
  256.     
  257.     if not Draw.PupBlock("Billboard Render", block):
  258.         return
  259.     
  260.     # Set globals
  261.     GLOBALS['ob_sel'] = ob_sel
  262.     GLOBALS['me_ob'] = me_ob
  263.     GLOBALS['me_data'] = me_data
  264.     
  265.     Blender.Window.FileSelector(save_billboard, 'SAVE BILLBOARD', Blender.sys.makename(ext='.png'))
  266.     # save_billboard('/tmp/test.png')
  267.  
  268. if __name__=='__main__':
  269.     main()
  270.